#include "SDK30.H"
#include <Param.h>
#include <schvar_Def.h>
#include <fm_proto.h>
#include <fm_HMIService.h>
#include "fm_genpinpad.h"
#include "fm_UserInterface.h"

//uint8 flAmtOnly;
#define ZEROPAD 1               /* pad with zero */
#define SIGN    2               /* unsigned/signed long */
#define PLUS    4               /* show plus */
#define SPACE   8               /* space if plus */
#define LEFT    16              /* left justified */
#define SPECIAL 32              /* 0x */
#define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */

#define is_digit(c)     ((c) >= '0' && (c) <= '9')
static FILE *devHandle[4]={NULL,NULL,NULL,NULL};
//static int DisplayHeaderStatus_FM;

//static int Lang;
static int fnt;
uint8 updt;
int fnts,MAXDISP;
uint8 framest;
static uint8 tertype;
char dispbuffer[30];
static uint8 smartdspadjust;

extern int GET_CHAR(void);

extern void _trace(const char * format,...);
#if 0
#define do_div(num,base) ({ \
int __res; \
__res = ((unsigned long) num) % (unsigned) base; \
num = ((unsigned long) num) / (unsigned) base; \
__res; }) 

static char * number(char * str, long num, int base, int size, int precision ,int type)
{
        char c,sign,tmp[66];
        const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
        int i;
        int res; 

        if (type & LARGE)
                digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        if (type & LEFT)
                type &= ~ZEROPAD;
        if (base < 2 || base > 36)
                return 0;
        c = (type & ZEROPAD) ? '0' : ' ';
        sign = 0;
        if (type & SIGN) {
                if (num < 0) {
                        sign = '-';
                        num = -num;
                        size--;
                } else if (type & PLUS) {
                        sign = '+';
                        size--;
                } else if (type & SPACE) {
                        sign = ' ';
                        size--;
                }
        }
        if (type & SPECIAL) {
                if (base == 16)
                        size -= 2;
                else if (base == 8)
                        size--;
        }
        i = 0;
        if (num == 0)
                tmp[i++]='0';
        else while (num != 0)
                {
                    res = ((unsigned long) num) % (unsigned) base; 
                    num = ((unsigned long) num) / (unsigned) base; 
                    tmp[i++] = digits[res];
                }
        if (i > precision)
                precision = i;
        size -= precision;
        if (!(type&(ZEROPAD+LEFT)))
                while(size-->0)
                        *str++ = ' ';
        if (sign)
                *str++ = sign;
		
        if (type & SPECIAL)
        {
                if (base==8)
                        *str++ = '0';
                else if (base==16) {
                        *str++ = '0';
                        *str++ = digits[33];
                }
        }
        if (!(type & LEFT))
                while (size-- > 0)
                        *str++ = c;
        while (i < precision--)
                *str++ = '0';
        while (i-- > 0)
                *str++ = tmp[i];
        while (size-- > 0)
                *str++ = ' ';
        return str;
}


static int skip_atoi(const char **s)
{
        int i=0;

        while (is_digit(**s))
                i = i*10 + *((*s)++) - '0';
        return i;
}
#endif

void getTerminalType(void)
{
	S_EQUIPEMENT Equipment;

	memset(&Equipment, 0x00, sizeof (S_EQUIPEMENT));
	PSQ_Donner_reference(&Equipment);
	tertype= Equipment.mod_equip[1];	
}

unsigned char pp_get_hardware_type(void)
{

	switch(tertype)
		{
			case TYPE_TERMINAL_SMART:
				//if (smartdspadjust)
				//	MAXDISP = 18;
				//else
					MAXDISP = 20;
				break;
			default:
				MAXDISP = 20;
				break;
		}

	return tertype;
}

int DisplayMenu( const char *szTitle, int bRadioButtons, int nDefaultChoice, 
				int nItems, char *Itemsy )
{

	//char Items[10][22];
	char Items[32][22];
	// Menu.
	StructList Menu;
	int nY;
	int nMaxX;
	int nMaxY;

	ENTRY_BUFFER Entry;

	int i;
	int nInput;

	int nReturn;

	memset((byte*)&Menu,0x00,sizeof(Menu));
	memcpy(Items,Itemsy,sizeof(Items));
	// Get Screen size.
	GetScreenSize( &nMaxY, &nMaxX );

	// For the menu height of the menu,
	nY = 0;

	if ((nDefaultChoice < 0) || (nDefaultChoice >= nItems))
	{
		nDefaultChoice = 0;
	}

	//
	CreateGraphics(_MEDIUM_);

	//
	memset( &Menu, 0, sizeof(Menu) );
	Menu.MyWindow.left   = 0;
	Menu.MyWindow.top    = nY;
	Menu.MyWindow.rigth  = nMaxX - 1;
	Menu.MyWindow.bottom = nMaxY - 1;
	if( nMaxY == 128 )
	{
		Menu.MyWindow.nblines = 10;
	}
	else
	{
		Menu.MyWindow.nblines = 5;
	}

	Menu.MyWindow.fontsize		= _MEDIUM_;
	Menu.MyWindow.type			= _PROPORTIONNEL_;
	Menu.MyWindow.font			= 0;
	Menu.MyWindow.correct		= _ON_;
	Menu.MyWindow.offset		= 0;
	Menu.MyWindow.shortcommand	= _ON_;
	if( bRadioButtons )
	{
		Menu.MyWindow.selected = _ON_;
	}
	else
	{
		Menu.MyWindow.selected = _OFF_;
	}

	Menu.MyWindow.thickness		= 2;
	Menu.MyWindow.border		= _ON_;
	Menu.MyWindow.popup			= _NOPOPUP_;
	Menu.MyWindow.first			= nDefaultChoice;
	Menu.MyWindow.current		= nDefaultChoice;
	Menu.MyWindow.time_out		= 60;
	Menu.MyWindow.title			= (unsigned char*)szTitle;

	for( i = 0; i < nItems; i++ )
	{
		Menu.tab[i] = (unsigned char*)Items[i];
	}

	G_List_Entry((void*)&Menu);
	ttestall(ENTRY, 0);
	nInput = Get_Entry((void*)&Entry);

//	_trace("Master DISPLAY MENU Get Entry : %d",Entry.d_entry[0]);
	
	switch( nInput )
	{
	case CR_ENTRY_OK:
		nReturn = (int)Entry.d_entry[0];
		break;

	case CR_ENTRY_NOK:
		nReturn = (int)__EXIT_KEY;
		break;

	default:
		nReturn = (int)__BACK_KEY;
		break;
	}

	
	return nReturn;
}



void Beeps( int Time , unsigned short PerMs )
{	
#if 0
	StartBuzzer( 0, 0x1300, 0x2600 );
	ttestall( 0, Time*PerMs );
	buzzer( PerMs );
	StopBuzzer();
#endif
	StartBuzzer( 10,0x10,0x1000 );
	ttestall( 0,1); //me*PerMs );
	//buzzer( 3 );
	StopBuzzer();
}

int GET_CHAR(void)
{
	int ret;
	ret = getchar();
	Beeps(1, 2);
	return ret;
}

void SetFrame(uint8 Status)
{
	framest=Status;
}

void pp_set_frame(uint8 bVisible)
{
	SetFrame(bVisible);
}

void pp_open_keyboard(void)
{
	if (!devHandle[DEV_KEYBOARD])
		devHandle[DEV_KEYBOARD]=fopen("KEYBOARD","r");
	
	return;
}

void pp_close_keyboard(void)
{
	if(devHandle[DEV_KEYBOARD])
		{
			fclose(devHandle[DEV_KEYBOARD]);
			devHandle[DEV_KEYBOARD]=NULL;
		}
}

uint8 pp_open_hmi(void)
{

	
	fnt=GetDefaultFont();
	fnts=_MEDIUM_;	
	SetFont(_MEDIUM_);
#if 1
	if (!devHandle[DEV_DISPLAY])
	devHandle[DEV_DISPLAY]=fopen("DISPLAY","a");
#endif
#if 0
	DisplayHeaderStatus_FM=StateHeader(0); // disable display header //disable by aan, 26 Juni 2008
		
	MAXDISP=21;
#endif
	pp_get_hardware_type();
	
	updt=TRUE;
	
	pp_display_clear(0);


//	if (!devHandle[DEV_KEYBOARD])
//		devHandle[DEV_KEYBOARD]=fopen("KEYBOARD","r");

	pp_open_keyboard();

	if (!devHandle[DEV_PRINTER])
		devHandle[DEV_PRINTER]=fopen("PRINTER","w-");
	
	//PaintGraphics();
	return 0;
}

void pp_close_hmi(void)
{
	SetDefaultFont(fnt);
//	if (framest)	
#if 0
		StateHeader(DisplayHeaderStatus_FM);	//disable by aan, 26 Juni 2008
#endif
	//_clrscr();
	//PaintGraphics();
#if 1
	if(devHandle[DEV_DISPLAY])
		{
	fclose(devHandle[DEV_DISPLAY]);			
	devHandle[DEV_DISPLAY]=NULL;
		}
#endif
//	if(devHandle[DEV_KEYBOARD])
//		{
//	fclose(devHandle[DEV_KEYBOARD]);
//	devHandle[DEV_KEYBOARD]=NULL;
//		}

	pp_close_keyboard();

	if(devHandle[DEV_PRINTER])
		{
	fclose(devHandle[DEV_PRINTER]);
	devHandle[DEV_PRINTER]=NULL;
		}
}


void pp_beep(uint32 count)
{
	unsigned short sh;

	sh=((unsigned short)count & 0xffff)*10;
	buzzer (sh);
}

uint8 pp_set_font(size_t fontNumber)
{
	fnts=(int)fontNumber;
	SetFont((int)fontNumber);
	return 0;
}

void pp_auto_update(uint8 bState)
{
	updt=bState;
}


	
void pp_display_update(void)
{
	PaintGraphics();
}

void pp_display_adjust(uint8 bState)
{
	smartdspadjust=bState;
}

void pp_settittle(char* tittle)
{

	memset(dispbuffer,0x00,sizeof(dispbuffer));
	strcpy(dispbuffer," ");
	strcat(dispbuffer,tittle);
	
//	_trace("pp_set_title : %s", dispbuffer);
}


void pp_display_clear(uint32 line)
{
	int nMaxX,l;
	int nMaxY;
	int lFontSize=0 ;

	GetScreenSize( &nMaxY, &nMaxX );
	if (!line)
	{
		_clrscr();
#if 1
		//if (framest)
		{
			_DrawRect( 0, 0, nMaxX-1, 8, 10, _ON_, _ON_ );
			_DrawRect( 0, 12,nMaxX-1 , nMaxY-1, 2, _ON_, _OFF_ ); // Empty Rect.
			DrawExtendedString( 0, 0, dispbuffer, _ON_,_MEDIUM_ ,_PROPORTIONNEL_);		
	
			PaintGraphics();		
		}

		return;
#endif		
	}
	
	switch( fnts )
	{
	case _SMALL_:
	case _MEDIUM_:
		lFontSize = 10;
		
		break;
	case _LARGE_:
	case _XLARGE_:
		lFontSize = 15;
		break;
	default:
		break;
	}

	l=(lFontSize*(line-1))+15;

	//_DrawRect
	_SetArea(3,l ,nMaxX-3, l+lFontSize, _OFF_ ); // Empty Rect.
}

void pp_display_text4(char *tittle, 
	char * prompt1, promptAttrib_t attrib1,
	char * prompt2, promptAttrib_t attrib2,
	char * prompt3, promptAttrib_t attrib3,
	char * prompt4, promptAttrib_t attrib4)
{
	//int nMaxX,nMaxY;
	//char tittle2[30];
#if 0	
	GetScreenSize( &nMaxY, &nMaxX );	
	_clrscr();
	//_DrawRect( 0, 0, nMaxX-1, 8, 10, _ON_, _ON_ );
	//_DrawRect( 0, 12,nMaxX-1 , nMaxY-1, 2, _ON_, _OFF_ ); // Empty Rect.
	sprintf(tittle2,">>%s", tittle);
	DrawExtendedString( 5, 0, tittle2, _OFF_,_MEDIUM_ ,_PROPORTIONNEL_);		
	PaintGraphics();	
#endif	
	if (prompt1)	pp_display_text(1,0, prompt1, attrib1);
	if (prompt2)	pp_display_text(2,0, prompt2, attrib2);
	if (prompt3)	pp_display_text(3,0, prompt3, attrib3);
	if (prompt4)	pp_display_text(4,0, prompt4, attrib4);
}

uint8 pp_display_text(uint32 line, uint32 col, char * prompt, promptAttrib_t attrib)
{
	long lFontSize=0,k;	
	int iStrPixelNum;//, addon;
//	int maxdisp;
	promptAttrib_t align_t;
	int ln,cl,ke=0;
	char prtprompt[50];

	memset(prtprompt, 0x00, sizeof prtprompt);
	strcpy((char*)prtprompt, prompt);
	ln=strlen(prtprompt);
	//pp_set_font(_POLICE5x7_);
	//ln=strlen(prompt);
	
	if (line>4)
		line-=4;

	if (attrib & PT_CLEAR)
		pp_display_clear(line);
			
		
	switch( fnts )
	{
	case _SMALL_:
	case _MEDIUM_:
	
			lFontSize = 10;
//		maxdisp=21;	
		break;
	case _LARGE_:
	case _XLARGE_:
		lFontSize = 15;
//		maxdisp=16;
		break;
	default:
		break;
	}
	
	align_t= attrib & SPP_ALIGN_MASK;
	cl = 0;
	pp_get_hardware_type();
	switch(align_t)
	{		
		case PT_ALIGN_CENTER:			
				{
					cl= ((MAXDISP-ln)/2);
					if ((MAXDISP-ln) % 2)
						cl++;
				}
				
				if ((pp_get_hardware_type() == TYPE_TERMINAL_SMART) && (smartdspadjust))		
					cl--;
			
			break;
		case PT_ALIGN_RIGHT:				
			if (pp_get_hardware_type() == TYPE_TERMINAL_SMART) 
			{
				if (smartdspadjust)
					cl=(18-ln)-4;	
				else
					cl=(18-ln);
			}
			else
				cl=(MAXDISP-ln);

			if (ln>4)
		{
			ke=(ln-4)*2;			
		}
			break;
		default:
			cl=col;			
			break;
	}
	

	//if(pp_get_hardware_type() == TYPE_TERMINAL_SMART)
	//	addon = MAXDISP;
	//else
	//	addon = 16;
	
	iStrPixelNum= (lFontSize*(line-1))+16;
	k= (attrib & PT_INVERSE_ON)?_ON_:_OFF_;
//	_trace("pp_display_text : %s", prompt);
	if((pp_get_hardware_type() == TYPE_TERMINAL_SMART) && (smartdspadjust))
		DrawExtendedString( ((cl)*StringWidth("M"))+3+ke, iStrPixelNum, prompt, k,_POLICE5x7_,_FIXED_WIDTH_);//_POLICE4x7_ ,_NORMALE_);
	else	
		DrawExtendedString( ((cl)*StringWidth("S"))+3, iStrPixelNum, prompt, k,_POLICE5x7_,_FIXED_WIDTH_);//_POLICE4x7_ ,_NORMALE_);
	return 0;
}

uint8 pp_display_graphic(uint32 x, uint32 y, uint32 width, uint32 height, void const* graphic)
{
	SetBitmap(x, y, (unsigned char*)graphic,_OFF_);
	SetArea(0, width, 128, height,_OFF_);
	return 0;
}

uint8 pp_keyboard_entry_free(char* buf, uint8 min, uint8 max, uint32 options, uint8 timeout)
{
	
	int isel;
	int num,x,y;

	if (!(options & KBD_DISPLAY_ORIGINAL))//aan
		buf[0]=0x00;

	num=(options & KBD_DISPLAY_NUMERIC)==KBD_DISPLAY_NUMERIC?1:0;

	y= ((options>>SPP_LINE_SHIFT) & 7)+1;
	x= (options >>SPP_COL_SHIFT) & 31;
	isel=HelperManageInput( buf, y, x, min,max, num, timeout*100 );
	if (isel==__ENTER_KEY)
		return strlen(buf);
	
	return __EXIT_KEY;
}

uint8 pp_password_entry_prompts( char* password, uint32 options, uint8 timeout)
{
	int x,y;
	int max;
	int ret;

	y= ((options>>SPP_LINE_SHIFT) & 7)+1;
	x= (options >>SPP_COL_SHIFT) & 31;
	max=(options & 0x0f);
	ret=PasswordEntry(password,y,x,max,max,TRUE,TIMEOUT);
	//pp_hex_dump("Pass",&ret,4);
	return ret;
	
}

uint8 pp_keyboard_entry( char* buf, uint8 min, uint8 max, uint32 options, uint8 timeout)
{
	int x,y;
	
	y= ((options>>SPP_LINE_SHIFT) & 7)+1;
	x= (options >>SPP_COL_SHIFT) & 31;
	if ((options & KBD_SHOW_LAST_KEY)==0)
		memset(buf,0x00,max);
		
	return PasswordEntry(buf,y,x,min,max,FALSE,TIMEOUT);
	
}

uint8 pp_get_key(uint32 timeout)
{
	uint16 per;
	
	per=ttestall(KEYBOARD, timeout*100);
	if (per & KEYBOARD)
		return kbdRead();
	else
		return 0;	
}

char pp_getchar(void)
{
	return getc(devHandle[DEV_KEYBOARD]);
}

char kbdRead(void)

{
    int  input;
    char key;;
   	
    
      key=GET_CHAR();

       switch(key) {
	   	  case T_SKHAUT	: input=VK_UP;break;
		  case T_SKBAS	: input=VK_DOWN;break;
                case T_ANN		: input = VK_CANCEL ; break;  
                case T_POINT	: input = VK_FUNCTION; break;  
		  case T_VAL		: input = 	VK_ENTER; break;
		  case T_APAP	: input = VK_FEED;break;	
                case T_SK1		: input = VK_F1; break;  
		  case T_SK2		: input= VK_F2;break;		
		  case T_SK3		: input= VK_F3;break;
		  case T_SK4		: input = VK_F4   ; break;                
                case T_CORR	: input = VK_CLEAR; break;  
                default			: input = key;
            }
    
    return input;
}

uint8 pp_get_acceptable_key(uint32 acceptable, uint32 timeout)
{
	char key;
	uint32 key_t=0;
	uint16 tm;
			
	do
	{

		tm=ttestall(KEYBOARD, timeout*100);	

		if ((tm & KEYBOARD)==0)
			return 0;		
		
		switch(key=kbdRead())
		{
			case VK_F1: key_t=ACCEPT_VK_F1;break;
			case VK_F2: key_t=ACCEPT_VK_F2;break;
			case VK_F3: key_t=ACCEPT_VK_F3;break;
			case VK_F4: key_t=ACCEPT_VK_F4;break;
			case VK_FEED: key_t=ACCEPT_VK_FEED;break;
			case VK_FUNCTION: key_t=ACCEPT_VK_FUNCTION;break;
			case VK_CLEAR:key_t=ACCEPT_VK_CLEAR;break;
			case VK_CANCEL:key_t=ACCEPT_VK_CANCEL;break;
			case VK_0:key_t=ACCEPT_VK_0;break;
			case VK_1:key_t=ACCEPT_VK_1;break;
			case VK_2:key_t=ACCEPT_VK_2;break;
			case VK_3:key_t=ACCEPT_VK_3;break;
			case VK_4:key_t=ACCEPT_VK_4;break;
			case VK_5:key_t=ACCEPT_VK_5;break;
			case VK_6:key_t=ACCEPT_VK_6;break;
			case VK_7:key_t=ACCEPT_VK_7;break;
			case VK_8:key_t=ACCEPT_VK_8;break;
			case VK_9:key_t=ACCEPT_VK_9;break;
			case VK_ENTER:key_t=ACCEPT_VK_ENTER;break;

			//aan, 23 Juli 2007 nambahin acceptable key untuk up n down key
			case VK_UP:key_t=ACCEPT_VK_F11;break;
			case VK_DOWN:key_t=ACCEPT_VK_F12;break;
		}

		

//		}while(acceptable & key);	
	}while(!(acceptable & key_t));	

	return key;
}


void Backlight( int bOn )
{
#ifndef WIN32 
      if( bOn == 1 )
       {
            // Start Backlight (for 15 seconds).
            StartRetroEclairage( 4, 0 , 100 );
      }
      else
      {
            // Stop backlight.
            StopRetroEclairage();
      }
#endif
}


//End Add
void pp_light_on(int m_on)
{
	if (m_on)
		Backlight(1);
	else
		Backlight(0);
}

byte pp_KeyboardGetStatus(void)
{
	byte kbdStatus = 0;
	status(devHandle[DEV_KEYBOARD], &kbdStatus);
	return kbdStatus;
}

byte pp_PrinterGetStatus(void)
{
	byte prtStatus = 0;
	status(devHandle[DEV_PRINTER], &prtStatus);
	return prtStatus;
}

byte pp_IsOutOfPaper(void)
{
	return ((pp_PrinterGetStatus() & PAPER_OUT )? TRUE : FALSE);
}
void xx_linefeed(uint8 lines)
{
	byte ln;	
	for(ln=0;ln < lines; ln++)
		fprintf(devHandle[DEV_PRINTER],"\x0D\x0A");
	
}

void debugPrint(char *txt)
{
	//always set to normal printing mode n DEFAULT printing mode
	char ctrlStr[5];
	ctrlStr[0]=0;
	strcpy(&ctrlStr[0],"\x1B\x46");
	fprintf(devHandle[DEV_PRINTER],ctrlStr);
	strcpy(&ctrlStr[0],"\x1B\x40");
	fprintf(devHandle[DEV_PRINTER],ctrlStr);	
	fprintf(devHandle[DEV_PRINTER],txt);

}

void pp_hex_dump(char *txt, void * buffer, uint16 len)
{
	char tg[25];
	char *ptr;
	uint16 i;
	uint8 n, index=0;
	ptr = (char *)buffer;
	n = 0;

	memset(tg,0x00,sizeof(tg));
	strcpy(tg, txt);
	strcat(tg,"\n");
	//debugPrint(mode, txt);
	debugPrint( tg);
	sprintf(tg, "LEN:%u Addr:%p", len, buffer);
	strcat(tg, "\n");
	debugPrint( tg);
	memset( tg, 0x00, 25 );
	for(i=0; i<len; i++)
	{
		if (n == 0)
			sprintf(&tg[n*3], "%02u|%02X ", index, *(uint8 *)&ptr[i]);
		else
			sprintf(&tg[n*3+3], "%02X ", *(uint8 *)&ptr[i]);

		if( n == 6 )
		{
			strcat(tg, "\n");
			debugPrint( tg);
			index++;
			n = 0;
			memset( tg, 0x00, 25 );
		}
		else
			n++;
	}
	if (n != 0)
		{
		strcat(tg, "\n");
		debugPrint(tg);
		}
	xx_linefeed(5);
}


unsigned int pp_ttestall(unsigned int events,unsigned int TimeOut)
{
	return ttestall(events, TimeOut);
}

int hmi_cmd(ST_hmi *hmi)
{
	switch(hmi->hmi_cmd)
	{
	case HMI_OPEN:
		return pp_open_hmi();
		break;
	case HMI_CLOSE:
		pp_close_hmi();
		break;			
	case HMI_LIGHT:
		pp_light_on(hmi->etat.mbool);
		break;
	case HMI_BEEP:
		pp_beep(hmi->etat.mtime);
		break;
	case HMI_TESTALL:
		hmi->retval.retuint=pp_ttestall(hmi->etat.mttestall.events, hmi->etat.mttestall.timeout);
		break;
	case HMIK_OPEN_KBD:
		pp_open_keyboard();
		break;
	case HMIK_CLOSE_KBD:
		pp_close_keyboard();
		break;
	case HMI_GET_HARDWARE:
		hmi->retval.reserved = pp_get_hardware_type();
		break;
	default:
		return STOP;
	}
	return FCT_OK;
}

#if 0
int fvsprintf(char *buf, const char *fmt, va_list args)
{
        int len;
        unsigned long num;
        int i, base;
        char * str;
        const char *s;

        int flags;              /* flags to number() */

        int field_width;        /* width of output field */
        int precision;          /* min. # of digits for integers; max
                                   number of chars for from string */
        int qualifier;          /* 'h', 'l', or 'L' for integer fields */

        for (str=buf ; *fmt ; ++fmt) {
                if (*fmt != '%') {
                        *str++ = *fmt;
                        continue;
                }

                /* process flags */
                flags = 0;
                repeat:
                        ++fmt;          /* this also skips first '%' */
                        switch (*fmt) {
                                case '-': flags |= LEFT; goto repeat;
                                case '+': flags |= PLUS; goto repeat;
                                case ' ': flags |= SPACE; goto repeat;
                                case '#': flags |= SPECIAL; goto repeat;
                                case '0': flags |= ZEROPAD; goto repeat;
                                }

                /* get field width */
                field_width = -1;
                if (is_digit(*fmt))
                        field_width = skip_atoi(&fmt);
                else if (*fmt == '*') {
                        ++fmt;
                        /* it's the next argument */
                        field_width = va_arg(args, int);
                        if (field_width < 0) {
                                field_width = -field_width;
                                flags |= LEFT;
                        }
                }

                /* get the precision */
                precision = -1;
                if (*fmt == '.') {
                        ++fmt;
                        if (is_digit(*fmt))
                                precision = skip_atoi(&fmt);
                        else if (*fmt == '*') {
                                ++fmt;
                                /* it's the next argument */
                                precision = va_arg(args, int);
                        }
                        if (precision < 0)
                                precision = 0;
                }

                /* get the conversion qualifier */
                qualifier = -1;
                if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
                        qualifier = *fmt;
                        ++fmt;
                }

                /* default base */
                base = 10;

                switch (*fmt) {
                case 'c':
                        if (!(flags & LEFT))
                                while (--field_width > 0)
                                        *str++ = ' ';
                        *str++ = (unsigned char) va_arg(args, int);
                        while (--field_width > 0)
                                *str++ = ' ';
                        continue;

                case 's':
                        s = va_arg(args, char *);
                        if (!s)
                                s = "<NULL>";

                        len = strlen(s); //, precision);

                        if (!(flags & LEFT))
                                while (len < field_width--)
                                        *str++ = ' ';
                        for (i = 0; i < len; ++i)
                                *str++ = *s++;
                        while (len < field_width--)
                                *str++ = ' ';
                        continue;

                case 'p':
                        if (field_width == -1) {
                                field_width = 2*sizeof(void *);
                                flags |= ZEROPAD;
                        }
                        str = number(str,
                                (unsigned long) va_arg(args, void *), 16,
                                field_width, precision, flags);
                        continue;


                case 'n':
                        if (qualifier == 'l') {
                                long * ip = va_arg(args, long *);
                                *ip = (str - buf);
                        } else {
                                int * ip = va_arg(args, int *);
                                *ip = (str - buf);
                        }
                        continue;

                /* integer number formats - set up the flags and "break" */
                case 'o':
                        base = 8;
                        break;

                case 'X':
                        flags |= LARGE;
                case 'x':
                        base = 16;
                        break;

                case 'd':
                case 'i':
                        flags |= SIGN;
                case 'u':
                        break;

                default:
                        if (*fmt != '%')
                                *str++ = '%';
                        if (*fmt)
                                *str++ = *fmt;
                        else
                                --fmt;
                        continue;
                }
                if (qualifier == 'l')
                        num = va_arg(args, unsigned long);
                else if (qualifier == 'h')
                {
                        if (flags & SIGN)
                                num = (unsigned long)va_arg(args, short);
                        else
                                num = (unsigned long)va_arg(args, unsigned short);
                }
                else if (flags & SIGN)
                        num = va_arg(args, int);
                else
                        num = va_arg(args, unsigned int);
				
                str = number(str, num, base, field_width, precision, flags);
        }
        *str = '\0';
        return str-buf;
}

#endif

void pp_pprintf(char *fmt, ...)
{   	
    va_list arg;
    char buffer[100];

    va_start(arg, fmt);  

#ifdef __GNUC__
	vsprintf(buffer,fmt,&arg);
#else
	vsprintf(buffer,fmt,arg);
#endif
    va_end(arg);

    fprintf(devHandle[DEV_PRINTER], buffer);
}

#ifdef IMAM_COMMS
void xx_pprintf(char *fmt, ...)
{   	
    va_list arg;
    char buffer[100];

    va_start(arg, fmt);  

#ifdef __GNUC__
	vsprintf(buffer,fmt,&arg);
#else
	vsprintf(buffer,fmt,arg);
#endif
    va_end(arg);

    fprintf(devHandle[DEV_PRINTER], buffer);
}

#endif

void pp_print(char *txt, int wait, int attrib)
{
#define C_NORMAL         "\x14""\x1b""F"
#define C_CONDENSED      "\x0f"
#define C_LARGE          "\x1b""E"

	switch(attrib)
	{
		case PP_PRINT_NORMAL:
			fprintf(devHandle[DEV_PRINTER],C_NORMAL);
			break;			
		case PP_PRINT_CONDESED:
			fprintf(devHandle[DEV_PRINTER],C_CONDENSED);
			break;
		case PP_PRINT_LARGE:
			fprintf(devHandle[DEV_PRINTER],C_LARGE);
			break;
	}
	fprintf(devHandle[DEV_PRINTER],txt);
	if (wait)
		ttestall(PRINTER, wait);
}

int printer_cmd(ST_hmi *hmi)
{
	switch(hmi->hmi_cmd)
	{
		case HMIP_GETSTATUS:
			hmi->retval.ret=pp_PrinterGetStatus();
			break;
		case HMIP_ISOUTPAPER:
			hmi->retval.ret=pp_IsOutOfPaper();
			break;
		case HMIP_PRINT:
			//printf(hmi->etat.buffer);
			pp_print(hmi->etat.buffer,0,0);			
			break;
		case HMIP_DEBUG	:
			pp_hex_dump( hmi->etat.pdebug.tittle, hmi->etat.pdebug.buffer, hmi->etat.pdebug.len);
			break;
		default:
			return STOP;
	}
			
		
	return FCT_OK;
}

int keyboard_cmd(ST_hmi *hmi)
{
	switch(hmi->hmi_cmd)
	{
	case HMIK_GETKEY:
		hmi->retval.ret=pp_get_key(hmi->etat.keyb.timeout);		
		break;
	case HMIK_READ:
		hmi->retval.ret=kbdRead();
		break;
	case HMIK_GET_ACCEPTABLE_KEY:		
		hmi->retval.ret=pp_get_acceptable_key(hmi->etat.keyb.AcceptedKey, hmi->etat.keyb.timeout);
		break;
	case HMIK_ENTRY_FREE:
		hmi->retval.ret=pp_keyboard_entry_free(hmi->etat.mkentry.buf, 
			hmi->etat.mkentry.min, hmi->etat.mkentry.max, 	hmi->etat.mkentry.options, 	hmi->etat.mkentry.timeout);
		strcpy(hmi->retval.buffer, hmi->etat.mkentry.buf);
		break;
	case HMIK_ENTRY_PWD:
		hmi->retval.ret= pp_password_entry_prompts( hmi->etat.mkentry.buf, hmi->etat.mkentry.options, hmi->etat.mkentry.timeout);			
		strcpy(hmi->retval.buffer, hmi->etat.mkentry.buf);
		break;
	case HMIK_ENTRY:
		hmi->retval.ret= pp_keyboard_entry(hmi->etat.mkentry.buf, 
			hmi->etat.mkentry.min, hmi->etat.mkentry.max, 	hmi->etat.mkentry.options, 	hmi->etat.mkentry.timeout);
		strcpy(hmi->retval.buffer, hmi->etat.mkentry.buf);
		break;		
	default:
		return STOP;	
	}
	return FCT_OK;
}

int display_cmd(ST_hmi *hmi)
{
	switch(hmi->hmi_cmd)
	{		
		case HMID_DISP_CLEAR:			
			pp_display_clear(hmi->etat.line);
			break;
		case HMID_DISP_FRAME:
			pp_set_frame(hmi->etat.mframe);
			break;			
		case HMID_DISP_PRINT:			
			//return pp_display_text(hmi->etat.disp.line, hmi->etat.disp.col,  hmi->etat.disp.prompt, hmi->etat.disp.attrib);
			hmi->retval.ret= pp_display_text(hmi->etat.disp.line, hmi->etat.disp.col,  hmi->etat.disp.prompt, hmi->etat.disp.attrib);
			break;
		case HMID_DISP_SETFONT:			
			//return pp_set_font(hmi->etat.mfont);
			hmi->retval.ret= pp_set_font(hmi->etat.mfont);
			break;
		case HMID_MENU:			
			hmi->retval.ret=DisplayMenu( hmi->etat.dpmenu.szTitle,hmi->etat.dpmenu.bRadioButtons, hmi->etat.dpmenu.nDefaultChoice, 				
				hmi->etat.dpmenu.nItems,hmi->etat.dpmenu.Itemsy );
			break;
		case HMID_AUTOUPDATE:
			pp_auto_update((uint8)hmi->etat.mbool);
			break;
		case HMID_UPDATE:			
			pp_display_update();
			break;
		case HMID_DISP_ADJUST:
			pp_display_adjust((uint8)hmi->etat.mbool);
			break;
		case HMID_SETTITTLE:			
			pp_settittle(hmi->etat.buffer); 
			break;
		case HMID_GRAPHIC:			
			//pp_display_graphic(hmi->etat.mgraph.x, hmi->etat.mgraph.y,hmi->etat.mgraph.width,hmi->etat.mgraph.height,hmi->etat.mgraph.graphic);
			hmi->retval.ret=pp_display_graphic(hmi->etat.mgraph.x, hmi->etat.mgraph.y,hmi->etat.mgraph.width,hmi->etat.mgraph.height,hmi->etat.mgraph.graphic);
			break;
		case HMID_DISP_PRINT4:
			pp_display_text4(hmi->etat.mdisp4.tittle, 
					hmi->etat.mdisp4.prompt1, hmi->etat.mdisp4.attrib1, 
					hmi->etat.mdisp4.prompt2, hmi->etat.mdisp4.attrib2,
					hmi->etat.mdisp4.prompt3, hmi->etat.mdisp4.attrib3, 
					hmi->etat.mdisp4.prompt4, hmi->etat.mdisp4.attrib4);
			break;		
		default:
			return STOP;
		
	}

	return FCT_OK;
 
}

int Service_HMI_call(int nSize, ST_hmi *hmi)
{

	int retval=0;
	
	switch(hmi->hmi_id)
	{
		case SERVICE_HMI_CALL_DISPLAY:			
			retval=display_cmd(hmi);
			break;
			
		case SERVICE_HMI_CALL_KEYBOARD:			
			retval=keyboard_cmd(hmi);
			break;	
			
		case SERVICE_HMI_CALL_PRINTER:
			mask_event(devHandle[DEV_PRINTER], PRINT_END | PRINT_BUFFER_EMPTY | PRINT_ERROR | PAPER_OUT | ERR_BUFFER);
			retval=printer_cmd(hmi);
			break;	
		
		case SERVICE_HMI_CALL_GENERAL:
			retval=hmi_cmd(hmi);
			break;
		default:
			return STOP;	
	}
	return FCT_OK;
}

void GetCurrentTime(char *date, char *time)
{
    DATE stCurDate;
    int i = 0;
    read_date(&stCurDate);

    memcpy(date + i, stCurDate.year, 2);
    i += 2;
    date[i++] = '-';
    memcpy(date + i, stCurDate.month, 2);
    i += 2;
    date[i++] = '-';
    memcpy(date + i, stCurDate.day, 2);

    i = 0;
    memcpy(time + i, stCurDate.hour, 2);
    i += 2;
    time[i++] = ':';
    memcpy(time + i, stCurDate.minute, 2);
}

void traceUsbCom(char *i_pcBuf, unsigned long i_lBufLen, char *i_pcTitle)
{
#ifdef MAKE_TRACE
	unsigned char buf[200];
	int length = 0;
	char sCurDate[8+1], sCurTime[8+1];
	char deviceName[10];
	int device_name;
		
	FILE *fpTrace = NULL;

	    //if (TheSysPara.debug_flag != 9)
	        //return ;

	    if ((i_lBufLen >= 150) && (i_lBufLen != 0xff))
	        return ;

	    if (strlen(i_pcBuf) >= 150 || strlen(i_pcTitle) >= 150)
	        return ;

		device_name = 0;
	    if (device_name == 0)
	        strcpy(deviceName, "COM5");
	    else if (device_name == 1)
	        strcpy(deviceName, "COM0");
	    else
	        strcpy(deviceName, "COM2");

	    fpTrace = fopen(deviceName, "rw");
	    if (fpTrace == NULL)
	        return ;

	    mask_event(fpTrace, COM_REC_NOT_EMPTY);
	    //format(deviceName, 9600, 8, 1, NO_PARITY, EVEN);
	    format(deviceName, 9600, 8, 1, NO_PARITY, EVEN);
	    reset_buf(fpTrace, _receive_id);

	    memset(buf, 0, sizeof(buf));
		memset(sCurDate, 0, sizeof(sCurDate));
		memset(sCurTime, 0, sizeof(sCurTime));
		GetCurrentTime(sCurDate,sCurTime);
		sprintf(buf+length, "[%s %s]->",sCurDate,sCurTime);
	    length += strlen(buf);
	    if (i_pcTitle != NULL)
	    {
	        memcpy(buf + length, i_pcTitle, strlen(i_pcTitle));
	        length += strlen(i_pcTitle);
	    }
	    if (i_lBufLen == 0xff)
	    {
	        memcpy(buf + length, i_pcBuf, strlen(i_pcBuf));
	        length += strlen(i_pcBuf);
	    }
	    else
	    {
	        memcpy(buf + length, i_pcBuf, i_lBufLen);
	        length += i_lBufLen;
	    }
	    memcpy(buf + length, "\r\n", 2);
	    length += 2;
	    fwrite(buf, 1, length, fpTrace);
	    ttestall(0, 10  );

	fclose(fpTrace);
#endif
}

void _trace(const char * format,...)
{
#ifdef MAKE_TRACE
	char newt[512];
	va_list liste;

	va_start(liste,format);
#ifdef __GNUC__
	vsprintf(newt,format,&liste);
#else
	vsprintf(newt,format,liste);
#endif
	traceUsbCom(newt, strlen(newt), "MASTER : ");
#endif
}

void _trace5(const char * format,...)
{
#ifdef MAKE_TRACE
	char newt[512];
	va_list liste;

	va_start(liste,format);
#ifdef __GNUC__
	vsprintf(newt,format,&liste);
#else
	vsprintf(newt,format,liste);
#endif
//	traceUsbCom(newt, strlen(newt), "MASTER : ");
     pp_print(newt,0,PP_PRINT_NORMAL);
#endif
}



int  TraceTofile(uint8 *buffer, uint32 length)
{
uint8 *	ptr=buffer;
//uint8 	more_records	= 0;//ptr[0];
int 		iRet;
uint32 len;
//FMFILE * fid1;
S_FS_FILE *fh; 

char openMode[5];
char nameTemp[40];
	
	

   memset(nameTemp,0x00,sizeof nameTemp);

      strcpy(openMode,"a");
      sprintf(nameTemp,"/%s/%s.DAT","HOST","TRACE");

	

	   	  
	len = length;
	fh= FS_open(nameTemp, openMode);
	if (fh==NULL)
	//if( (fh= FS_open(nameTemp, openMode)))
	//if( (fid1= FM_fopen(nameTemp, openMode)) == 0)
	   {
	     
		//sysDisplayError("NVM OPEN FAILED", 1000);
		return -1;
	    }

	iRet=FS_write ( ptr, 1, len, fh);// != len/2)
//	iRet=FM_fwrite( ptr, 1, len, fid1);// != len/2)
//	_trace4("Fwrite %d==%s",iRet,nameTemp);
	//FM_fclose(fid1);
	
	FS_close(fh);


  	return 1 ;

}

void _trace4(const char * format,...)
{
#ifdef TRACE_FILE  

char newt[512];
	va_list liste;

	va_start(liste,format);
#ifdef __GNUC__
	vsprintf(newt,format,&liste);
#else
	vsprintf(newt,format,liste);
  strcat (newt,"\r\n");
  TraceTofile(newt, strlen(newt));
  #endif
  #endif
#ifdef MAKE_TRACE
	char newt[512];
	va_list liste;

	va_start(liste,format);
#ifdef __GNUC__
	vsprintf(newt,format,&liste);
#else
	vsprintf(newt,format,liste);
#endif
   
	traceUsbCom(newt, strlen(newt), "MASTER : ");
#endif
}

void _trace_DSP2( char *txt, void * buffer, uint16 len)
{
#ifdef MAKE_TRACE

	char tg[30];
	char *ptr;
	uint16 i;
	uint8 n, index=0;
	ptr = (char *)buffer;
	n = 0;

	memset(tg,0x00,sizeof(tg));
	_trace4("===================S T A R T=====================");
	strcpy(tg, txt);
	//strcat(tg,"\n");
	//debugPrint(mode, txt);
	//debugPrint(mode, tg);
	_trace4(tg);
	sprintf(tg, "LEN:%u Addr:%p", len, buffer);
	//strcat(tg, "\n");
	//debugPrint(mode, tg);
	_trace4(tg);
	memset( tg, 0x00, 25 );
	for(i=0; i<len; i++)
	{
		if (n == 0)
			sprintf(&tg[n*3], "%02u|%02X ", index, *(uint8 *)&ptr[i]);
		else
			sprintf(&tg[n*3+3], "%02X ", *(uint8 *)&ptr[i]);

		if( n == 6 )
		{
			//strcat(tg, "\n");
			//debugPrint(mode, tg);
			_trace4(tg);
			index++;
			n = 0;
			memset( tg, 0x00, 25 );
		}
		else
			n++;
	}
	if (n != 0)
		{
		//strcat(tg, "\n");
		//debugPrint(mode, tg);
		_trace4(tg);
		}
	//xx_linefeed(5);
	_trace4("===================E N D=======================");
	
#endif
	
}


